﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace VisionApp.Entity
{
    public class UltraHighAccurateTimer
    {
        private long clockFrequency;

        private int intervalMs;                     // interval in mimliseccond;
        long currTime;
        long nextTriggerTime;
        ///
        /// Timer inteval in milisecond
        ///
        public int Interval
        {
            get { return intervalMs; }
            set
            {
                intervalMs = value;
                intevalTicks = (long)((double)value * (double)clockFrequency / (double)1000);
            }
        }

        private long intevalTicks;

        ///
        /// Pointer to a variable that receives the current performance-counter value, in counts.
        ///
        ///
        /// If the function succeeds, the return value is nonzero.
        ///
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

        ///
        /// Pointer to a variable that receives the current performance-counter frequency,
        /// in counts per second.
        /// If the installed hardware does not support a high-resolution performance counter,
        /// this parameter can be zero.
        ///
        ///
        /// If the installed hardware supports a high-resolution performance counter,
        /// the return value is nonzero.
        ///
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);

        public UltraHighAccurateTimer()
        {
            if (QueryPerformanceFrequency(out clockFrequency) == false)
            {
                // Frequency not supported
                throw new Win32Exception("QueryPerformanceFrequency() function is not supported");
            }
        }

        public void Init()
        {
            GetTick(out currTime);
            //nextTriggerTime = currTime + intevalTicks;
        }

        public void Sleep()
        {
            while (currTime < nextTriggerTime)
            {
                GetTick(out currTime);
            }   // wailt an interval
            //nextTriggerTime = currTime + intevalTicks;
        }

        public void Wait(int ms)
        {
            Interval = ms;
            nextTriggerTime = currTime + intevalTicks;
            Sleep();
        }

        public bool GetTick(out long currentTickCount)
        {
            if (QueryPerformanceCounter(out currentTickCount) == false)
                throw new Win32Exception("QueryPerformanceCounter() failed!");
            else
                return true;
        }

        ~UltraHighAccurateTimer()
        {
        }
    }
}
